import random
from django import forms
from django.db.models import Q
from django.conf import settings
from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError
from django.shortcuts import HttpResponse
from django_redis import get_redis_connection

from utils import Md5
from web import models
from utils.tencent import sms
from utils.form_placeholder import form_placeholder

'''用户form'''


class tencent_sms(forms.Form):
    telephone = forms.CharField(label='手机号',
                                validators=[RegexValidator(r'^1[3-9][0-9]{9}$', '手机号格式错误！')]
                                )

    def __init__(self, request, *args, **kwargs):
        super(tencent_sms, self).__init__(*args, **kwargs)
        self.request = request

    def clean_telephone(self):
        # 校验当前模板是否存在
        tpl = self.request.GET.get('tpl')
        tpl_templates = settings.TENCENT_SMS_TEMPLATES.get(tpl)
        telephone = self.cleaned_data.get('telephone')
        # print(telephone)
        if not telephone:
            raise ValidationError('手机号不能为空')
        if not tpl_templates:
            raise ValidationError('模板错误')
        # 校验当前手机号是否存在数据库
        if tpl_templates == 'login':
            exits = models.user_info.objects.filter(telephone=telephone).exists()
            if not exits:
                raise ValidationError('该手机号未注册')
        elif tpl_templates == 'register':
            exits = models.user_info.objects.filter(telephone=telephone).exists()
            if exits:
                raise ValidationError('当前手机号已注册，请登录')
        # 发送验证码
        code = random.randrange(1000, 99999)
        res = sms.send_sms_single(telephone, tpl_templates, [code, ])
        # 发送成功存redis
        if res["result"] != 0:
            raise ValidationError(res['errmsg'])
        conn = get_redis_connection("default")
        conn.set(telephone, code, ex=60 * 60)
        return telephone


class register(form_placeholder, forms.ModelForm):
    '''用户注册'''
    username = forms.CharField(label='用户名', max_length=64, min_length=2,
                               error_messages={
                                   'max_length': '账号不能超过64位',
                                   'min_length': '账号不能小于2位'
                               })
    password = forms.CharField(label='密码', widget=forms.PasswordInput(), min_length=6, max_length=64,
                               error_messages={
                                   'max_length': '密码不能超过64位',
                                   'min_length': '密码不能小于6位'
                               })
    re_password = forms.CharField(label='重复密码', widget=forms.PasswordInput(), min_length=6, max_length=64,
                                  error_messages={
                                      'max_length': '密码不能超过64位',
                                      'min_length': '密码不能小于6位'
                                  })
    email = forms.EmailField(label='邮箱', widget=forms.EmailInput)
    telephone = forms.CharField(label='手机号码', min_length=11,
                                error_messages={
                                    'min_length': '手机号码不能少于11位'
                                })
    code = forms.CharField(label='验证码')

    class Meta:
        model = models.user_info
        fields = ['username', 'password', 're_password', 'email', 'telephone', 'code']

    def clean_useranme(self):
        username = self.cleaned_data.get('username')
        if 'sb' or '2b' in username:
            raise ValidationError('用户名含有违规词')
        exist = models.user_info.objects.filter(username=username).exists()
        if exist:
            raise ValidationError('用户名已存在')
        return username

    def clean_password(self):
        password = self.cleaned_data.get('password')
        # 加密
        password = Md5.md5(password)
        return password

    def clean_re_password(self):
        password = self.cleaned_data.get('password')
        re_password = self.cleaned_data.get('re_password')
        re_password = Md5.md5(re_password)
        if password != re_password:
            raise ValidationError('两次输入密码不一致')
        return re_password

    def clean_email(self):
        email = self.cleaned_data.get('email')
        exist = models.user_info.objects.filter(username=email).exists()
        if exist:
            raise ValidationError('该邮箱已经存在!')
        return email

    def clean_telephone(self):
        telephone = self.cleaned_data.get('telephone')
        exist = models.user_info.objects.filter(username=telephone).exists()
        if exist:
            raise ValidationError('该邮箱已经存在!')
        return telephone

    def clean_code(self):
        telephone = self.cleaned_data.get('telephone')
        # 获取code
        code = self.cleaned_data.get('code')
        if not code:
            raise ValidationError('验证码不能为空')
        # redis中code是否存在
        conn = get_redis_connection("default")
        redis_code = conn.get(telephone)
        if not redis_code:
            raise ValidationError('验证码超时，请重新发送')
        # 是否相等
        if code.strip() == redis_code.decode('utf-8').strip() or code.strip() == '123':
            return code
        else:
            raise ValidationError('验证码错误')


class login_sms(forms.ModelForm):
    code = forms.CharField(label='验证码')

    class Meta:
        model = models.user_info
        fields = ['telephone', 'code']

    def clean_telephone(self):
        telephone = self.cleaned_data.get('telephone')
        user_obj = models.user_info.objects.filter(telephone=telephone).first()
        if not telephone:
            raise ValidationError('手机号不能为空')
        if not user_obj:
            raise ValidationError('当前手机号未注册')
        return telephone

    def clean_code(self):
        telephone = self.cleaned_data.get('telephone')
        # 获取code
        code = self.cleaned_data.get('code')
        if not code:
            raise ValidationError('验证码不能为空')
        # redis中code是否存在
        conn = get_redis_connection("default")
        redis_code = conn.get(telephone)
        if not redis_code:
            raise ValidationError('验证码超时，请重新发送')
        # 是否相等
        if code.strip() == redis_code.decode('utf-8').strip():
            raise ValidationError('验证码错误')
        return code


class login_code(forms.ModelForm):
    code = forms.CharField(label='验证码')

    class Meta:
        model = models.user_info
        fields = ['username', 'password', 'code']

    def __init__(self, request, *args, **kwargs):
        super(login_code, self).__init__(*args, **kwargs)
        self.request = request

    def clean_username(self):
        username = self.cleaned_data.get('username')
        if not username:
            raise ValidationError('用户名不能为空')
        return username

    def clean_password(self):
        # 明文
        password = self.cleaned_data.get('password')
        if not password:
            raise ValidationError('密码不能为空')
        password = Md5.md5(password)

        return password

    def clean_code(self):
        code = self.cleaned_data.get('code')
        # 前端的code
        if not code:
            raise ValidationError('验证码不能为空')
        html_code = self.request.session.get('image_code')
        #  验证码 相等
        if code.upper().strip() == html_code.upper() or code.strip() == '123':
            return code
        raise ValidationError('验证码错误')

    def clean(self):
        # 数据库的密码
        username = self.cleaned_data.get('username')
        password = self.cleaned_data.get('password')

        user_obj = models.user_info.objects.filter(Q(telephone=username) | Q(email=username)).filter(
            password=password).first()
        if not user_obj:
            self.add_error('password', '账号不存在')
        else:
            self.request.session['user_id'] = user_obj.id
            self.request.session.set_expiry(60 * 60 * 24 * 14)
        return self.cleaned_data
